﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Data.ConnectionUI;
using Bing.Toolkit.Data;

namespace Bing.Studio
{
    public delegate void ClickMenuHandler(object sender, DatabaseExplorerEventArgs e);

    public partial class FrmDatabaseExplorer : BaseForm
    {
        public event ClickMenuHandler ClickMenuEvent;

        public FrmDatabaseExplorer()
        {
            InitializeComponent();
        }

        /****************************************************************************************************/

        #region /*自定义方法*/

        private void InitLoadTreeViewData()
        {
            var dbs = DatabaseInfomationStorage.GetAll();
            foreach (var entry in dbs)
            {
                AddDatabaseToTreeView(entry);
            }
        }

        private void AddDatabaseToTreeView(DatabaseInfomationStorage dbInfomation)
        {
            TreeNode nodeServer;
            if (tvDatabase.Nodes.ContainsKey(dbInfomation.ServerName))
            {
                nodeServer = tvDatabase.Nodes[dbInfomation.ServerName];
            }
            else
            {
                nodeServer = new TreeNode(dbInfomation.ServerName, 0, 0);
                nodeServer.Name = dbInfomation.ServerName;
                nodeServer.ContextMenuStrip = this.contextMenuStrip1;
                tvDatabase.Nodes.Add(nodeServer);
            }
            TreeNode nodeDatabase = new TreeNode(dbInfomation.DataBaseName, 1, 1);
            nodeDatabase.Tag = dbInfomation;
            nodeDatabase.ContextMenuStrip = this.contextMenuStrip2;
            nodeServer.Nodes.Add(nodeDatabase);
            if (!nodeServer.IsExpanded)
            {
                nodeServer.Expand();
            }
        }

        private void AddDatabase()
        {
            var dialog = new DataConnectionDialog();
            //设置SqlServer数据源
            dialog.DataSources.Add(DataSource.SqlDataSource);
            //设置Odbc数据源
            //dialog.DataSources.Add(DataSource.OdbcDataSource);
            //设置默认数据源
            dialog.SelectedDataSource = DataSource.SqlDataSource;
            //设置默认驱动
            dialog.SelectedDataProvider = DataProvider.SqlDataProvider;

            if (DataConnectionDialog.Show(dialog) == DialogResult.OK)
            {
                var strConnectionString = dialog.ConnectionString;
                var strProviderName = dialog.SelectedDataProvider.Name;

                DatabaseTest dbTest = new DatabaseTest(strConnectionString, strProviderName);
                Exception ex;

                if (dbTest.Test(out ex))
                {
                    var storage = new DatabaseInfomationStorage()
                    {
                        ConnectionString = strConnectionString,
                        ProviderName = strProviderName,
                        DataBaseName = dbTest.GetDatabaseName(),
                        ServerName = dbTest.GetServerName()
                    };
                    storage.Save();
                    AddDatabaseToTreeView(storage);
                }
                else
                {
                    SendNotification(ex);
                }
            }
        }

        private void RemoveDatabase(TreeNode node)
        {
            DatabaseInfomationStorage dbInfomation = node.Tag as DatabaseInfomationStorage;
            dbInfomation.Remove();
            node.Remove();
        }

        private void RemoveAllDatabase()
        {
            TreeNode node = tvDatabase.SelectedNode;
            for (var i = 0; i < node.Nodes.Count; i++)
            {
                RemoveDatabase(node.Nodes[i]);
            }
            node.Remove();
        }

        private void ConnectionDatabase()
        {
            TreeNode nodeCurrent = tvDatabase.SelectedNode;
            if (nodeCurrent.Nodes.Count == 0)
            {
                DatabaseInfomationStorage dbInfomation = nodeCurrent.Tag as DatabaseInfomationStorage;
                DatabaseTest dbTest = new DatabaseTest(dbInfomation.ConnectionString, dbInfomation.ProviderName);
                Exception ex;
                if (dbTest.Test(out ex))
                {
                    var ds = new SQLServerDataStructuresHelper(dbInfomation.ConnectionString);
                    var tableNameArray = ds.GetTalbeNameArray();
                    var viewNameArray = ds.GetViewNameArray();
                    var spNameArray = ds.GetStoredProcedureNamesArray();

                    FillDatabaseNode(tvDatabase.SelectedNode, "表", tableNameArray, this.contextMenuStrip3);
                    FillDatabaseNode(tvDatabase.SelectedNode, "视图", viewNameArray, this.contextMenuStrip4);
                    FillDatabaseNode(tvDatabase.SelectedNode, "存储过程", spNameArray, this.contextMenuStrip5);

                    nodeCurrent.Expand();
                }
                else
                {
                    nodeCurrent.SelectedImageIndex = 2;
                    nodeCurrent.ImageIndex = 2;
                    SendNotification(ex);
                }
            }
        }

        private void FillDatabaseNode(TreeNode parent, string text, List<string> subArray, ContextMenuStrip cms)
        {
            var node = new TreeNode(text, 3, 3);
            foreach (var entry in subArray)
            {
                var subNode = new TreeNode(entry, 4, 4);
                subNode.ContextMenuStrip = cms;
                node.Nodes.Add(subNode);
            }
            parent.Nodes.Add(node);
        }

        private void RefreshDatabase()
        {
            tvDatabase.SelectedNode.Nodes.Clear();
            ConnectionDatabase();
        }

        private void ClickMenu(DatabaseExplorerActionType enumType)
        {
            if (ClickMenuEvent != null)
            {
                TreeNode node = tvDatabase.SelectedNode.Parent.Parent;
                DatabaseInfomationStorage dbInfomation = node.Tag as DatabaseInfomationStorage;
                ClickMenuEvent(this, new DatabaseExplorerEventArgs(
                    dbInfomation.ServerName, 
                    dbInfomation.DataBaseName, 
                    dbInfomation.ConnectionString, 
                    dbInfomation.ProviderName, 
                    enumType, 
                    tvDatabase.SelectedNode.Text));
            }
        }

        #endregion

        /****************************************************************************************************/

        private void FrmDatabaseExplorer_Load(object sender, EventArgs e)
        {
            InitLoadTreeViewData();
        }

        private void tsbtnAddDatabase_Click(object sender, EventArgs e)
        {
            AddDatabase();
        }

        private void tsbtnDelDatabase_Click(object sender, EventArgs e)
        {
            if (tvDatabase.SelectedNode.Level == 1)
            {
                RemoveDatabase(tvDatabase.SelectedNode);
            }
            else if (tvDatabase.SelectedNode.Level == 0)
            {
                RemoveAllDatabase();
            }
        }

        private void tsbtnConnection_Click(object sender, EventArgs e)
        {
            ConnectionDatabase();
        }

        private void tvDatabase_MouseDown(object sender, MouseEventArgs e)
        {
            TreeNode node = tvDatabase.GetNodeAt(e.X, e.Y);
            if (node != null)
            {
                tvDatabase.SelectedNode = node;
            }
            var level = tvDatabase.SelectedNode.Level;

            this.tsbtnDelDatabase.Enabled = (level == 0 || level == 1);
            this.tsbtnConnection.Enabled = level == 1;
            this.tsbtnRefresh.Enabled = level == 1;
        }

        private void tvDatabase_Leave(object sender, EventArgs e)
        {
            this.tsbtnDelDatabase.Enabled = false;
            this.tsbtnConnection.Enabled = false;
            this.tsbtnRefresh.Enabled = false;
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            AddDatabase();
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            RemoveAllDatabase();
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            RemoveDatabase(tvDatabase.SelectedNode);
        }

        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            ConnectionDatabase();
        }

        private void tsbtnRefresh_Click(object sender, EventArgs e)
        {
            RefreshDatabase();
        }

        private void toolStripMenuItem5_Click(object sender, EventArgs e)
        {
            RefreshDatabase();
        }

        private void tvDatabase_DoubleClick(object sender, EventArgs e)
        {
            if (tvDatabase.SelectedNode.Level == 1)
            {
                ConnectionDatabase();
            }
        }

        private void toolStripMenuItem6_Click(object sender, EventArgs e)
        {
            ClickMenu(DatabaseExplorerActionType.SQLQuery);
        }

        private void toolStripMenuItem7_Click(object sender, EventArgs e)
        {
            ClickMenu(DatabaseExplorerActionType.CodeGenerator);
        }

        private void toolStripMenuItem8_Click(object sender, EventArgs e)
        {
            ClickMenu(DatabaseExplorerActionType.InsertScript);
        }



        /****************************************************************************************************/

    }

    public class DatabaseExplorerEventArgs : EventArgs
    {
        public string Sever { get; private set; }

        public string Database { get; private set; }

        public string ConnectionString { get; set; }

        public string ProviderName { get; set; }

        public DatabaseExplorerActionType ActionType { get; private set; }

        public string CommandObject { get; private set; }

        public DatabaseExplorerEventArgs(
            string strServer, 
            string strDatabase, 
            string strConn, 
            string strProvider,
            DatabaseExplorerActionType enumType,
            string strCommandObject)
        {
            Sever = strServer;
            Database = strDatabase;
            ConnectionString = strConn;
            ProviderName = strProvider;
            ActionType = enumType;
            CommandObject = strCommandObject;
        }
    }

    public enum DatabaseExplorerActionType
    { 
        SQLQuery = 1,
        CodeGenerator = 2,
        InsertScript = 3
    }
}
